namespace Felbot.Protocol {
    //Todo: redo this class based on the new way of BattleNetPacketThread....... eh not required for operation so hide for now
    #region
    /*
    /// <summary>Controls connection to Battle.net realm.</summary>
    public class BattleNetRealmPacketThread : PacketThread
    {
        private BattleNetPacketThread m_BnPacketThread;

        private string m_UniqueUsername;
        private string m_CharacterName;
        private int m_Port;
        private int m_ClientToken;
        private int m_Status;
        private int[] m_Chunk;

        // This is used for various delegate invocations
        private delegate void AnonymousDelegate();

        // This is used to create anonymous methods for timer callbacks.
        private delegate void TimerCallbackDelegate(Object stateInfo);
        
        /// <summary>
        /// This will construct a BattleNetRealmPacketThread
        /// </summary>
        /// <param name="main">Instance of frmProfile that message will be printed on</param>
        /// <param name="parent">The parent BattleNetPacketThread.</param>
        /// <param name="a_iClientToken">The cleint token.</param>
        /// <param name="a_iStatus">The status integer.</param>
        /// <param name="a_iChunk1">The chunk1 int array.</param>
        /// <param name="a_iChunk2">The chunk2 int array.</param>
        /// <param name="a_bServerIP">The server IP as a byte array.</param>
        /// <param name="a_iPortValue">The port value.</param>
        /// <param name="a_sUniqueUsername">The unique username.</param>
        public BattleNetRealmPacketThread(frmProfile main, BattleNetPacketThread parent, int clientToken, uint status, int[] chunk1, int[] chunk2, byte[] serverIP, int portValue, string uniqueUsername) : base(main)
        {
            m_BnPacketThread = parent;

            m_Chunk = new int[chunk1.Length + chunk2.Length];
            for (int i = 0; i < chunk1.Length + chunk2.Length; i++)
                if (i < chunk1.Length)
                    m_Chunk[i] = chunk1[i];
                else
                    m_Chunk[i] = chunk2[i - chunk1.Length];
            m_Port = portValue;
            m_ClientToken = clientToken;
            m_Status = unchecked((int) status);
            m_UniqueUsername = uniqueUsername;

            // Create the state moniting timer.
            m_SocketStateMonitorTimer = new Timer(new TimerCallback((TimerCallbackDelegate)delegate(Object stateInfo)
            {
                #region Socket State Checking Delegate
                if (m_Socket != null && m_Socket.Connected != m_SocketConnected)
                {
                    m_SocketConnected = m_Socket.Connected;
                    if (m_Socket.Connected == true)
                    {
                        m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.GreenYellow, "[BOTNET] Connected!"));
                        Socket_Connected();
                    }
                    else
                    {
                        m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[BOTNET] Disconnected!"));
                        Socket_Disconnect();
                    }
                }
                #endregion
            }), null, 0, 500);

            // Create the socket reading thread.
            m_SocketReader = new Thread(new ThreadStart((AnonymousDelegate)delegate()
            /// <summary>
            /// This function will be constantly looping for the duration of the existance
            /// of an instance of this class, forked to the background in another Thread.
            /// This will handle all the reading of the socket.
            /// </summary>
            {
                byte[] header = new byte[3];
                short length;
                byte id;
                byte[] data;
                while (true)
                {
                    Thread.Sleep(10);
                    if (m_Socket != null && m_Socket.Connected == true)
                    {
                        if (m_Socket.Available > 0)
                        {
                            try
                            {
                                #region Proxy Packet
                                base.Proxy();
                                #endregion

                                #region MCP Packet
                                if (m_Socket.Available >= 3)
                                {
                                    m_Socket.Receive(header, 0, 3, SocketFlags.Peek);

                                    id = header[1];
                                    length = (short) BitConverter.ToUInt16(header, 0);
                                    data = new byte[length];
                                    if (m_Socket.Available >= length)
                                    {
                                        m_Socket.Receive(data, 0, length, SocketFlags.None);
                                        if (m_frmProfile.Main.ShowPackets)
                                        {
                                            m_frmProfile.RichTextBox.AddTextNodes(
                                                new TextNode(
                                                    new Font(new FontFamily("Lucida Console"), 12, FontStyle.Regular, GraphicsUnit.Point),
                                                    Color.DodgerBlue,
                                                    "[REALM] RECIEVED PACKET 0x" + id.ToString("X") + " " + ((BattleNetRealmPacketIDs) id).ToString() + ":" + Environment.NewLine +
                                                    DataFormatter.Format(data)
                                                )
                                            );
                                        }
                                        ParsePacket(new DataReader(data));
                                    }
                                }
                                #endregion
                            }
                            catch (SocketException)
                            {
                            }
                        }
                    }
                }
            }));
            m_SocketReader.IsBackground = true;
            m_SocketReader.Start();
        }

        /// <summary>
        /// This is called by ReadSocket when a new packet is received.
        /// </summary>
        /// <param name="a_prReader">An instance of PacketReader containg the packet's data</param>
        protected override void ParsePacket(DataReader reader)
        {
            int length = reader.ReadInt16();
            int id = reader.ReadInt32();
            switch ((BattleNetRealmPacketIDs) id)
            {
                #region 0x02 Handle MCP_CHARCREATE
                case BattleNetRealmPacketIDs.MCP_CHARCREATE:
                    int m_iCharCreateResult = reader.ReadInt32();
                    #region Result Codes
                    switch (m_iCharCreateResult)
                    {
                        case 0x00:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.GreenYellow, "[REALM] Character create succeeded."));
                            break;
                        case 0x14:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character create failed. Character already exists or you cannot create any more characters."));
                            return;
                        case 0x15:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character create failed. Character name invalid."));
                            return;
                        default:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character create failed. Unknown result code: 0x" + m_iCharCreateResult.ToString("X")));
                            return;
                    }
                    #endregion
                    //todo: clear channel list view?
                    SendPacket19();
                    break;
                #endregion

                #region 0x07 Handle MCP_CHARLOGON
                case BattleNetRealmPacketIDs.MCP_CHARLOGON:
                    int m_iCharLogonResult = reader.ReadInt32();
                    #region Result Codes
                    switch (m_iCharLogonResult)
                    {
                        case 0x00:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.GreenYellow, "[REALM] Character logon succeeded."));
                            break;
                        case 0x46:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character logon failed. Player not found."));
                            return;
                        case 0x7A:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character logon failed."));
                            return;
                        case 0x7B:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character logon failed. Character expired."));
                            return;
                        default:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character logon failed. Unknown result code: 0x" + m_iCharLogonResult.ToString("X")));
                            return;
                    }
                    #endregion
                    m_frmProfile.ChannelList.Chosen(m_CharacterName);
                    break;
                #endregion

                #region 0x0A Handle MCP_CHARDELETE
                case BattleNetRealmPacketIDs.MCP_CHARDELETE:
                    int m_iCharDeleteResult = reader.ReadInt32();
                    #region Result Codes
                    switch (m_iCharDeleteResult)
                    {
                        case 0x00:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.GreenYellow, "[REALM] Character deleted successfully."));
                            break;
                        case 0x49:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character delete failed. Character not found."));
                            return;
                        default:
                            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Character delete failed. Unknown result code: 0x" + m_iCharDeleteResult.ToString("X")));
                            return;
                    }
                    #endregion
                    m_frmProfile.ChannelList.Deleted(m_CharacterName);
                    break;
                #endregion

                #region 0x19 Handle MCP_CHARLIST2
                case BattleNetRealmPacketIDs.MCP_CHARLIST2:
                    reader.ReadInt16(); //number requested, 8
                    int m_iAccountCount = reader.ReadInt32();
                    int m_iReturnedCount = reader.ReadInt16();
                    int m_iCharExpireTime; string m_sCharName; string m_sCharStatString;
                    Dictionary<string, int> m_dictChars = new Dictionary<string, int>();
                    for (int i = 0; i < m_iReturnedCount; i++)
                    {
                        m_iCharExpireTime = reader.ReadInt32();
                        m_sCharName = reader.ReadCString();
                        m_sCharStatString = reader.ReadCString();
                        m_dictChars.Add("PX2D" + m_BnPacketThread.Realm + "," + m_sCharName + "," + m_sCharStatString, m_iCharExpireTime);
                    }
                    m_frmProfile.ChannelList.CharacterList(this, m_dictChars);
                    break;
                #endregion

                #region Default
                default:
                    m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Unhandled realm packet received! 0x" + id.ToString("X")));
                    break;
                #endregion
            }
        }

        /// <summary>Sends packet 0x01, MCP_STARTUP.</summary>
        private void SendPacket01()
        {
            McpPacket m_dpMcpBuffer = new McpPacket(BattleNetRealmPacketIDs.MCP_STARTUP);
            m_dpMcpBuffer.InsertInt32(m_ClientToken); //client token
            m_dpMcpBuffer.InsertInt32(m_Status); //status
            m_dpMcpBuffer.InsertInt32Array(m_Chunk); //chunk 1
            m_dpMcpBuffer.InsertInt32Array(g_iChunk2); //chunk 2
            m_dpMcpBuffer.InsertCString(m_UniqueUsername); //username
            SendPacket(m_dpMcpBuffer.GetData());
        }

        /// <summary>Sends packet 0x07, MCP_CHARLOGON.</summary>
        /// <param name="m_sCharName">The character to log onto.</param>
        public void SendPacket07(string m_sCharName)
        {
            m_CharacterName = m_sCharName;
            McpPacket m_dpMcpBuffer = new McpPacket(BattleNetRealmPacketIDs.MCP_CHARLOGON);
            m_dpMcpBuffer.InsertCString(m_sCharName);
            SendPacket(m_dpMcpBuffer.GetData());
        }

        /// <summary>Sends packet 0x0A, MCP_CHARDELETE.</summary>
        /// <param name="m_sCharName">The character to delete.</param>
        public void SendPacket0A(string m_sCharName)
        {
            m_CharacterName = m_sCharName;
            McpPacket m_dpMcpBuffer = new McpPacket(BattleNetRealmPacketIDs.MCP_CHARDELETE);
            m_dpMcpBuffer.InsertCString(m_sCharName);
            SendPacket(m_dpMcpBuffer.GetData());
        }

        /// <summary>Sends packet 0x19, MCP_CHARLIST2.</summary>
        private void SendPacket19()
        {
            McpPacket m_dpMcpBuffer = new McpPacket(BattleNetRealmPacketIDs.MCP_CHARLIST2);
            m_dpMcpBuffer.InsertInt32(0x08); //number, 8 characters
            SendPacket(m_dpMcpBuffer.GetData());
        }

        /// <summary>
        /// This is a public method to disconnect the socket.
        /// </summary>
        public override bool Socket_Disconnect()
        {
            if (base.Socket_Disconnect())
            {
                m_CharacterName = "";
                return true;
            }
            return false;
        }

        /// <summary>
        /// This is called when the connect is successful and all proxy-related stuff is complete (or no proxy related stuff is done at all)
        /// </summary>
        internal override void Socket_ConnectedComplete()
        {
            m_Connected = true;

            SendPacket01();

            m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Yellow, "[REALM] Authorizing.."));
        }
        
        /// <summary>
        /// This sends a packet across the socket.
        /// </summary>
        /// <param name="a_bData">Data</param>
        internal override void SendPacket(byte[] a_bData)
        {
            if (!m_Connected)
                return;
            try
            {
                m_Socket.Send(a_bData);
                if (m_frmProfile.Main.ShowPackets)
                {
                    m_frmProfile.RichTextBox.AddTextNodes(
                        new TextNode(
                            new Font(new FontFamily("Lucida Console"), 12, FontStyle.Regular, GraphicsUnit.Point),
                            Color.DodgerBlue,
                            "[REALM] SENT PACKET 0x" + a_bData[2].ToString("X") + ((BattleNetRealmPacketIDs) a_bData[2]).ToString() + ":" + Environment.NewLine +
                            DataFormatter.Format(a_bData)
                        )
                    );
                }
            }
            catch (Exception e)
            {
                if (e.Message == "An existing connection was forcibly closed by the remote host")
                {
                    m_ReconnectAttempts = 0;
                    m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] You are IPBanned, or you have lost your internet connection.  Please try connecting later."));
                    Socket_Disconnect();
                    return;
                }
                m_frmProfile.RichTextBox.AddTextNodes(new TextNode(Color.Red, "[REALM] Caught exception in SendPacket(): " + Environment.NewLine + e.ToString()));
            }
        }

        internal override void SendByte(byte bByte)
        {
            //this won't be called, do nothing
        }
    }

    //McpPacket, same as BncsPacket except different header.
    /*
    MBNCSUtil -- Managed Battle.net Authentication Library
    Copyright (C) 2005-2008 by Robert Paveza

    Redistribution and use in source and binary forms, with or without modification, 
    are permitted provided that the following conditions are met: 

    1.) Redistributions of source code must retain the above copyright notice, 
    this list of conditions and the following disclaimer. 
    2.) Redistributions in binary form must reproduce the above copyright notice, 
    this list of conditions and the following disclaimer in the documentation 
    and/or other materials provided with the distribution. 
    3.) The name of the author may not be used to endorse or promote products derived 
    from this software without specific prior written permission. 
    	
    See LICENSE.TXT that should have accompanied this software for full terms and 
    conditions.

    * /
    /// <summary>
    /// Completes a <see cref="DataBuffer">DataBuffer</see> implementation with the additional
    /// data used by the MCP protocol.
    /// </summary>
    internal sealed class McpPacket : DataBuffer
    {
        private BattleNetRealmPacketIDs m_id;

        /// <summary>
        /// Creates a new MCP packet with the specified packet ID.
        /// </summary>
        /// <param name="id">The MCP packet ID.</param>
        public McpPacket(BattleNetRealmPacketIDs id)
            : base()
        {
            m_id = id;
        }

        /// <summary>
        /// Gets or sets the ID of the packet as it was specified when it was created.
        /// </summary>
        public byte PacketID
        {
            get { return (byte) m_id; }
            set { m_id = (BattleNetRealmPacketIDs) value; }
        }

        /// <summary>
        /// Gets the total number of bytes in this packet, including the three-byte header.
        /// </summary>
        public override int Count
        {
            get
            {
                return base.Count + 3;
            }
        }

        /// <summary>
        /// Gets the data in this packet, including the three-byte header.
        /// </summary>
        /// <returns>A byte array containing the packet data.</returns>
        public override byte[] GetData()
        {
            byte[] data = new byte[Count];
            byte[] len = BitConverter.GetBytes((ushort)(Count & 0xffff));
            data[0] = len[0];
            data[1] = len[1];
            byte[] baseData = base.GetData();
            data[2] = (byte) m_id;

            Buffer.BlockCopy(baseData, 0, data, 3, baseData.Length);

            return data;
        }

        /// <summary>
        /// Gets a hex representation of this buffer.
        /// </summary>
        /// <returns>A string representing this buffer's contents in hexadecimal notation.</returns>
        public override string ToString()
        {
            return DataFormatter.Format(GetData());
        }
    }*/
    #endregion
}


